#include "SQLBinaryOperator.h"
#include "../../../utils/StringUtils.h"

SQLBinaryOperator SQLBinaryOperator::Union = SQLBinaryOperator(make_string_ptr("UNION"), 0);
SQLBinaryOperator SQLBinaryOperator::COLLATE = SQLBinaryOperator(make_string_ptr("COLLATE"), 20);
SQLBinaryOperator SQLBinaryOperator::BitwiseXor = SQLBinaryOperator(make_string_ptr("^"), 50);
SQLBinaryOperator SQLBinaryOperator::BitwiseXorEQ = SQLBinaryOperator(make_string_ptr("^="), 110);
SQLBinaryOperator SQLBinaryOperator::Multiply = SQLBinaryOperator(make_string_ptr("*"), 60);
SQLBinaryOperator SQLBinaryOperator::Divide = SQLBinaryOperator(make_string_ptr("/"), 60);
SQLBinaryOperator SQLBinaryOperator::DIV = SQLBinaryOperator(make_string_ptr("DIV"), 60); // mysql integer division
SQLBinaryOperator SQLBinaryOperator::Modulus = SQLBinaryOperator(make_string_ptr("%"), 60);
SQLBinaryOperator SQLBinaryOperator::Mod = SQLBinaryOperator(make_string_ptr("MOD"), 60);
SQLBinaryOperator SQLBinaryOperator::Add = SQLBinaryOperator(make_string_ptr("+"), 70);
SQLBinaryOperator SQLBinaryOperator::Subtract = SQLBinaryOperator(make_string_ptr("-"), 70);
SQLBinaryOperator SQLBinaryOperator::SubGt = SQLBinaryOperator(make_string_ptr("->"), 20);
SQLBinaryOperator SQLBinaryOperator::SubGtGt = SQLBinaryOperator(make_string_ptr("->>"), 20);
SQLBinaryOperator SQLBinaryOperator::PoundGt = SQLBinaryOperator(make_string_ptr("#>"), 20);
SQLBinaryOperator SQLBinaryOperator::PoundGtGt = SQLBinaryOperator(make_string_ptr("#>>"), 20);
SQLBinaryOperator SQLBinaryOperator::QuesQues = SQLBinaryOperator(make_string_ptr("??"), 20);
SQLBinaryOperator SQLBinaryOperator::QuesBar = SQLBinaryOperator(make_string_ptr("?|"), 20);
SQLBinaryOperator SQLBinaryOperator::QuesAmp = SQLBinaryOperator(make_string_ptr("?&"), 20);
SQLBinaryOperator SQLBinaryOperator::LeftShift = SQLBinaryOperator(make_string_ptr("<<"), 80);
SQLBinaryOperator SQLBinaryOperator::RightShift = SQLBinaryOperator(make_string_ptr(">>"), 80);
SQLBinaryOperator SQLBinaryOperator::BitwiseAnd = SQLBinaryOperator(make_string_ptr("&"), 90);
SQLBinaryOperator SQLBinaryOperator::BitwiseOr = SQLBinaryOperator(make_string_ptr("|"), 100);
SQLBinaryOperator SQLBinaryOperator::GreaterThan = SQLBinaryOperator(make_string_ptr(">"), 110);
SQLBinaryOperator SQLBinaryOperator::GreaterThanOrEqual = SQLBinaryOperator(make_string_ptr(">="), 110);
SQLBinaryOperator SQLBinaryOperator::Is = SQLBinaryOperator(make_string_ptr("IS"), 110);
SQLBinaryOperator SQLBinaryOperator::LessThan = SQLBinaryOperator(make_string_ptr("<"), 110);
SQLBinaryOperator SQLBinaryOperator::LessThanOrEqual = SQLBinaryOperator(make_string_ptr("<="), 110);
SQLBinaryOperator SQLBinaryOperator::LessThanOrEqualOrGreaterThan = SQLBinaryOperator(make_string_ptr("<=>"), 110);
SQLBinaryOperator SQLBinaryOperator::LessThanOrGreater = SQLBinaryOperator(make_string_ptr("<>"), 110);
SQLBinaryOperator SQLBinaryOperator::IsDistinctFrom = SQLBinaryOperator(make_string_ptr("IS DISTINCT FROM"), 110);
SQLBinaryOperator SQLBinaryOperator::IsNotDistinctFrom = SQLBinaryOperator(make_string_ptr("IS NOT DISTINCT FROM"), 110);
SQLBinaryOperator SQLBinaryOperator::Like = SQLBinaryOperator(make_string_ptr("LIKE"), 110);
SQLBinaryOperator SQLBinaryOperator::SoudsLike = SQLBinaryOperator(make_string_ptr("SOUNDS LIKE"), 110);
SQLBinaryOperator SQLBinaryOperator::NotLike = SQLBinaryOperator(make_string_ptr("NOT LIKE"), 110);
SQLBinaryOperator SQLBinaryOperator::ILike = SQLBinaryOperator(make_string_ptr("ILIKE"), 110);
SQLBinaryOperator SQLBinaryOperator::NotILike = SQLBinaryOperator(make_string_ptr("NOT ILIKE"), 110);
SQLBinaryOperator SQLBinaryOperator::AT_AT = SQLBinaryOperator(make_string_ptr("@@"), 110); // postgresql textsearch
SQLBinaryOperator SQLBinaryOperator::SIMILAR_TO = SQLBinaryOperator(make_string_ptr("SIMILAR TO"), 110);
SQLBinaryOperator SQLBinaryOperator::POSIX_Regular_Match = SQLBinaryOperator(make_string_ptr("~"), 110);
SQLBinaryOperator SQLBinaryOperator::POSIX_Regular_Match_Insensitive = SQLBinaryOperator(make_string_ptr("~*"), 110);
SQLBinaryOperator SQLBinaryOperator::POSIX_Regular_Not_Match = SQLBinaryOperator(make_string_ptr("!~"), 110);
SQLBinaryOperator SQLBinaryOperator::POSIX_Regular_Not_Match_POSIX_Regular_Match_Insensitive = SQLBinaryOperator(make_string_ptr("!~*"), 110);
SQLBinaryOperator SQLBinaryOperator::Array_Contains = SQLBinaryOperator(make_string_ptr("@>"), 110);
SQLBinaryOperator SQLBinaryOperator::Array_ContainedBy = SQLBinaryOperator(make_string_ptr("<@"), 110);
SQLBinaryOperator SQLBinaryOperator::SAME_AS = SQLBinaryOperator(make_string_ptr("~="), 110);
SQLBinaryOperator SQLBinaryOperator::JSONContains = SQLBinaryOperator(make_string_ptr("?"), 110);
SQLBinaryOperator SQLBinaryOperator::RLike = SQLBinaryOperator(make_string_ptr("RLIKE"), 110);
SQLBinaryOperator SQLBinaryOperator::NotRLike = SQLBinaryOperator(make_string_ptr("NOT RLIKE"), 110);
SQLBinaryOperator SQLBinaryOperator::NotEqual = SQLBinaryOperator(make_string_ptr("!="), 110);
SQLBinaryOperator SQLBinaryOperator::NotLessThan = SQLBinaryOperator(make_string_ptr("!<"), 110);
SQLBinaryOperator SQLBinaryOperator::NotGreaterThan = SQLBinaryOperator(make_string_ptr("!>"), 110);
SQLBinaryOperator SQLBinaryOperator::IsNot = SQLBinaryOperator(make_string_ptr("IS NOT"), 110);
SQLBinaryOperator SQLBinaryOperator::Escape = SQLBinaryOperator(make_string_ptr("ESCAPE"), 110);
SQLBinaryOperator SQLBinaryOperator::RegExp = SQLBinaryOperator(make_string_ptr("REGEXP"), 110);
SQLBinaryOperator SQLBinaryOperator::NotRegExp = SQLBinaryOperator(make_string_ptr("NOT REGEXP"), 110);
SQLBinaryOperator SQLBinaryOperator::Equality = SQLBinaryOperator(make_string_ptr("="), 110);
SQLBinaryOperator SQLBinaryOperator::BitwiseNot = SQLBinaryOperator(make_string_ptr("!"), 130);
SQLBinaryOperator SQLBinaryOperator::Concat = SQLBinaryOperator(make_string_ptr("||"), 140);
SQLBinaryOperator SQLBinaryOperator::BooleanAnd = SQLBinaryOperator(make_string_ptr("AND"), 140);
SQLBinaryOperator SQLBinaryOperator::BooleanXor = SQLBinaryOperator(make_string_ptr("XOR"), 150);
SQLBinaryOperator SQLBinaryOperator::BooleanOr = SQLBinaryOperator(make_string_ptr("OR"), 160);
SQLBinaryOperator SQLBinaryOperator::Assignment = SQLBinaryOperator(make_string_ptr(":="), 169);
SQLBinaryOperator SQLBinaryOperator::PG_And = SQLBinaryOperator(make_string_ptr("&&"), 140);
SQLBinaryOperator SQLBinaryOperator::PG_ST_DISTANCE = SQLBinaryOperator(make_string_ptr("<->"), 20);

int SQLBinaryOperator::getPriority(SQLBinaryOperator_ptr operator_)
{
  return 0;
}

SQLBinaryOperator::SQLBinaryOperator(string_ptr name, int priority)
{
  this->name = name;
  this->nameLCase = StringUtils::toLower(name);
  this->priority = priority;
}

SQLBinaryOperator::SQLBinaryOperator(SQLBinaryOperator *sqlBinaryOperator)
{
  this->name = sqlBinaryOperator->name;
  this->nameLCase = sqlBinaryOperator->nameLCase;
  this->priority = sqlBinaryOperator->priority;
}

bool SQLBinaryOperator::isRelational()
{
  if (this->name->c_str() == Equality.name->c_str() ||
      this->name->c_str() == Like.name->c_str() ||
      this->name->c_str() == SoudsLike.name->c_str() ||
      this->name->c_str() == NotEqual.name->c_str() ||
      this->name->c_str() == GreaterThan.name->c_str() ||
      this->name->c_str() == GreaterThanOrEqual.name->c_str() ||
      this->name->c_str() == LessThan.name->c_str() ||
      this->name->c_str() == LessThanOrEqual.name->c_str() ||
      this->name->c_str() == LessThanOrGreater.name->c_str() ||
      this->name->c_str() == NotLike.name->c_str() ||
      this->name->c_str() == NotLessThan.name->c_str() ||
      this->name->c_str() == NotGreaterThan.name->c_str() ||
      this->name->c_str() == RLike.name->c_str() ||
      this->name->c_str() == NotRLike.name->c_str() ||
      this->name->c_str() == RegExp.name->c_str() ||
      this->name->c_str() == NotRegExp.name->c_str() ||
      this->name->c_str() == Is.name->c_str() ||
      this->name->c_str() == IsNot.name->c_str())
  {
    return true;
  }
  else
  {
    return false;
  }
}

bool SQLBinaryOperator::isArithmetic()
{
  if (this->name->c_str() == Add.name->c_str() ||
      this->name->c_str() == Subtract.name->c_str() ||
      this->name->c_str() == Multiply.name->c_str() ||
      this->name->c_str() == Divide.name->c_str() ||
      this->name->c_str() == DIV.name->c_str() ||
      this->name->c_str() == Modulus.name->c_str() ||
      this->name->c_str() == Mod.name->c_str())
  {
    return true;
  }
  else
  {
    return false;
  }
}
